<?php

namespace app\callback\controller;

use app\aliyun\controller\AliyunRtc;
use app\common\lib\rtc\ConsultSubscribe;
use think\Controller;
use think\Log;

/**
 * RTC 订阅回调
 */
class RtcSubscribe extends Controller
{
    /**
     * 写入日志前缀
     * @var string
     */
    private static $LOG_PRE = 'RTC消息的回调：';

    public function handle()
    {   // 8084
        try
        {
            $header = $this->request->header();
            $params = $this->request->param();
//            Log::write(self::$LOG_PRE . '请求数据：header=【' . json_encode($header) . '】,params=【' . json_encode($params) . '】', 'log', true);
            //回调鉴权
            $config = config('rtc');

            $signature = md5($config['subscribe_doamin'] . '|' . $header['ali-rtc-timestamp'] . '|' . $config['app_key']);
            if ($header['ali-rtc-signature'] !== $signature)
            {
                Log::write(self::$LOG_PRE . '回调鉴权失败！ header(ali-rtc-signature)=' . $header['ali-rtc-signature'] . ',signature=' . $signature, 'error', true);
                return;
            } else
            {
//                Log::write(self::$LOG_PRE . '回调鉴权成功！ header(ali-rtc-signature)=' . $header['ali-rtc-signature'] . ',signature=' . $signature, 'log', true);
                // 解析 频道信息
                $channelData = $this->decodeChannelIdInfo($params['ChannelId']);
                foreach ($params['Contents'] as $v)
                {
                    $event = $v['Event'];
                    if ($event === 'ChannelEvent')
                    {//ChannelEvent用户事件
                        //事件类型，取值：Open：会议开始。Close：会议结束。
                        if ($v['ChannelEvent']['EventTag'] === 'Open')
                        {//会议开始。
//                            Log::write(self::$LOG_PRE . '会议开始', 'log', true);
                        } elseif ($v['ChannelEvent']['EventTag'] === 'Close')
                        {//会议结束
//                            Log::write(self::$LOG_PRE . '会议结束', 'log', true);
                        }
                    } else if ($event === 'UserEvent')
                    {//UserEvent用户事件
//           {
//            "Event":"UserEvent",
//            "UserEvent":{
//                "UserId":"1",//用户ID
//                "EventTag":"UnpublishVideo",//事件类型，取值：
//Join：入会。
//Leave：离会。
//PublishVideo：开始推视频流。
//PublishAudio：开始推音频流。
//PublishScreen：开始屏幕共享。
//StopPublishVideo：停止推视频流。
//StopPublishAudio：停止推音频流。
//StopPublishScreen：停止屏幕共享。
//Roleupdate：角色切换。
//                "SessionId":"rURB4M4kxUW9EMqs4DkfTg2doU2RBX4b",//用户SessionID。
//                "Timestamp":1639978708,//事件发生的时间戳。
//                "ChannelProfile":"communication",
//                "US":282574490436612,
//                "Reason":1,//入会、离会原因（仅Join事件有），取值：
//
//1：正常入会、离会。
//2：重连入会（当前会中已有该用户实例，该用户再次入会）。
//3：跨频道转推。
//4：超时离会。
//5：用户启用新的会话，当前会话被挤下线。
//6：被踢出。
//7：频道解散。

//                "Role":1,//角色类型，取值：
//1：主播。
//2：观众。
//                "TerminalType":6,//终端类型，取值：
//1：Windows设备。
//2：Android设备。
//3：Mac设备。
//4：iOS设备。
//5：Linux设备。
//0：其他（只有Native SDK入会可以解析终端类型)。

//                "UserType":2//用户类型，取值：
//1：Native SDK。
//2：WebRTC(非小程序，非Native都归为WebRTC)。
//3：小程序。
//            }
                        switch ($v['UserEvent']['EventTag'])
                        {
                            case 'Join':    // 入会
                            {
                                $userData = $this->decodeUserInfo($v['UserEvent']['UserId']);
                                if ($userData['type'] === -1)
                                {   // 非法用户  踢出去
                                    $this->removeTerminals($params['ChannelId'], $v['UserEvent']['UserId']);
                                    return;
                                }
                                switch ($channelData['type'])
                                {
                                    case 'consult': // 咨询师
                                        Log::write(self::$LOG_PRE . ' 【连麦咨询】 ' . ($userData['type'] === 2 ? '咨询师' : '咨询用户') . ($userData['uid']) . '入会,Reason=' . $v['UserEvent']['Reason'], 'log', true);
                                        // 入会处理
                                        (new ConsultSubscribe())->Join($userData, $channelData['channel_id']);
                                        break;
                                    case 'consult2': // 咨询师
                                        Log::write(self::$LOG_PRE . ' 【连麦咨询】 ' . ($userData['type'] === 2 ? '咨询师' : '咨询用户') . ($userData['uid']) . '入会,Reason=' . $v['UserEvent']['Reason'], 'log', true);
                                        // 入会处理
                                        (new ConsultSubscribe())->Join2($userData, $channelData['channel_id']);
                                        break;
                                    default:
                                        // 非法渠道  踢出去
                                        $this->removeTerminals($params['ChannelId'], $v['UserEvent']['UserId']);
                                }
                                break;
                            }
                            case 'Leave':   // 离会
                            {
                                $userData = $this->decodeUserInfo($v['UserEvent']['UserId']);
                                if ($userData['type'] === -1)
                                {   // 非法用户  离会
                                    return;
                                }

                                switch ($channelData['type'])   // 频道 类型
                                {
                                    case 'consult': // 咨询 频道
//                                        Log::write(self::$LOG_PRE . ' 【连麦咨询】 ' . ($userData['type'] === 1 ? '咨询师' : '咨询用户') . ($userData['uid']) . '离会,Reason=' . $v['UserEvent']['Reason'], 'log', true);
                                        //  离会处理
                                        //  1：正常入会、离会。
                                        //  2：重连入会（当前会中已有该用户实例，该用户再次入会）。
                                        //  3：跨频道转推。
                                        //  4：超时离会。
                                        //  5：用户启用新的会话，当前会话被挤下线。
                                        //  6：被踢出。
                                        //  7：频道解散。
                                        if (in_array((int)$v['UserEvent']['Reason'], [1, 4, 7], true))
                                        {
                                            (new ConsultSubscribe())->Leave($userData, $channelData['channel_id']);
                                            // 删除 房间 信息
                                            (new AliyunRtc())->deleteRtcChannel('consult_' . $channelData['channel_id']);
                                        }
                                        break;
                                    case 'consult2': // 咨询 频道
//                                        Log::write(self::$LOG_PRE . ' 【连麦咨询】 ' . ($userData['type'] === 1 ? '咨询师' : '咨询用户') . ($userData['uid']) . '离会,Reason=' . $v['UserEvent']['Reason'], 'log', true);
                                        //  离会处理
                                        //  1：正常入会、离会。
                                        //  2：重连入会（当前会中已有该用户实例，该用户再次入会）。
                                        //  3：跨频道转推。
                                        //  4：超时离会。
                                        //  5：用户启用新的会话，当前会话被挤下线。
                                        //  6：被踢出。
                                        //  7：频道解散。
                                        if (in_array((int)$v['UserEvent']['Reason'], [1, 4, 7], true))
                                        {
                                            Log::write(self::$LOG_PRE . ' 【连麦咨询】ChannelId：' . $channelData['channel_id'] . '  ' . ($userData['type'] === 2 ? '咨询师' : '咨询用户') . ($userData['uid']) . '离会,Reason=' . $v['UserEvent']['Reason'], 'log', true);

                                            (new ConsultSubscribe())->Leave2($userData, $channelData['channel_id']);
                                            // 删除 房间 信息
                                            (new AliyunRtc())->rmEventSubAndDelRtcChannel($params['ChannelId']);
                                        }
                                        break;
                                    default:
                                        // 非法渠道  离会
                                }
                                break;
                            }
                        }
                    }
                }

            }
        }
        catch (\Exception $e)
        {
            Log::write(self::$LOG_PRE . "异常：{$e->getMessage()};File:{$e->getFile()};Line:{$e->getLine()}", 'error', true);
        }
    }

    /**
     * 解析 用户信息
     * @param string $uidData
     * @return array
     */
    private function decodeUserInfo(string $uidData)
    {
        $userData = explode('_', $uidData);
        if (count($userData) === 2)
        {
            switch ($userData[0])
            {
                case 'user':
                    $type = 1;
                    $uid = (int)$userData[1];
                    break;
                case 'astr':
                    $type = 2;
                    $uid = (int)$userData[1];
                    break;
                default:
                    $type = -1;
                    $uid = 0;
            }
            return [
                'type' => $type,   // -1 未知用户  1=>准有好事APP用户  2=>占星师
                'uid' => $uid,
            ];
        } else
        {
            return [
                'type' => -1,   // -1 未知用户  1=>准有好事APP用户  2=>占星师
                'uid' => 0,
            ];
        }
    }

    /**
     * 解析 渠道信息
     * @param string $channelIdData
     * @return array
     */
    private function decodeChannelIdInfo(string $channelIdData)
    {
        $channelData = explode('_', $channelIdData);
        if (count($channelData) === 2)
        {
            return [
                'type' => $channelData[0],   // 渠道类型
                'channel_id' => $channelData[1],     // 渠道ID
            ];
        } else
        {
            return [
                'type' => '',   // 渠道类型
                'channel_id' => 0,     // 渠道ID
            ];
        }
    }

    /**
     * 提出 频道
     * @param $channelId
     * @param $userId
     * @return void
     */
    private function removeTerminals($channelId, $userId)
    {
        // 自动踢出
        $result = (new AliyunRtc())->removeTerminals($channelId, [$userId]);
        //[
        //      'code' => 200,
        //      'msg' => '请求成功!',
        //      'data' =>[
        //           'result' =>[
        //              'RequestId' => '9695BD39-96CC-5E25-812C-DA83E60297C7',
        //              'Terminals' =>[
        //                  'Terminal' => [
        //                         0 =>[
        //                                  'Message' => 'ok',
        //                                  'Id' => '12346392',
        //                                   'Code' => 0,
        //                                ],
        //                  ],
        //              ],
        //          ],
        //      ],
        // ];
        if ($result['code'] === 200 && isset($result['data']['result']['Terminals']['Terminal']) && !empty($result['data']['result']['Terminals']['Terminal']))
        {
            Log::write("连麦回调：用户非法进入连麦，执行踢出操作--成功--；ChannelId:【{$channelId}】uid：【{$userId}】;踢出结果:" . json_encode($result), 'log');
        } else
        {
            Log::write("连麦回调：用户非法进入连麦，执行踢出操作--失败--；ChannelId:【{$channelId}】uid：【{$userId}】;踢出结果:" . json_encode($result), 'error');
        }
    }
}
